import tori.settings, tori.bird, tori.interface
import tori.instructions
import tori.bin, tori.binary
import pygtk, random
pygtk.require("2.0")
import gtk.glade
import gettext
_=gettext.gettext


class Simulator:
    def __init__(self, fitxategia, ezar):
        self.ezarpenak  = ezar    
        # Itzulpenak
        gtk.glade.bindtextdomain(self.ezarpenak.APP, self.ezarpenak.LOCALE_DIR)
        gtk.glade.textdomain(self.ezarpenak.APP)
        

        # Leiho berria sortu        
        self.fitxategia = fitxategia
        self.irteera    = ""
        self.makina     = tori.bird.Bird()
        self.wZuhaitza  = gtk.glade.XML(self.ezarpenak.GLADE_FILE, "SIMULATZAILEA")
        self.nagusia    = self.wZuhaitza.get_widget("SIMULATZAILEA")
        self.nagusia.set_icon_from_file(self.ezarpenak.ICON_FILE)
        gtk.window_set_default_icon_from_file(self.ezarpenak.LOGO_FILE)

        #Botoiak
        self.btnpikusi    =  self.wZuhaitza.get_widget("btnpikusi")
        self.btngelditu   =  self.wZuhaitza.get_widget("btngelditu")
        self.btnhurrengoa =  self.wZuhaitza.get_widget("btnhurrengoa")
        self.btngorde     =  self.wZuhaitza.get_widget("btngorde")
        self.btnstat      =  self.wZuhaitza.get_widget("btnstat")

        #Erregistroen zutabea
        self.erregistroak =  self.wZuhaitza.get_widget("erregistrozu")
        self.zutabeak_gehitu(self.erregistroak,("Erreg.","Balioa"))
        self.erregistro_lista = gtk.ListStore(str, str)
        self.erregistroak.set_model(self.erregistro_lista)
        self.erregistroak_berritu()

        #Memoriaren zutabea
        self.memoria = self.wZuhaitza.get_widget("memoria").get_buffer()
        #Irteera testua
        self.output  = self.wZuhaitza.get_widget("output").get_buffer()

        #Egoera zuhaitza
        self.egoerazu =  self.wZuhaitza.get_widget("egoerazu")
        self.zutabeak_gehitu(self.egoerazu,(_("Agindua"),_("Ri1"), _("Ri2"), _("Rh"), _("Memoria@"), _("Edukia")))
        self.egoera = gtk.ListStore(str, str, str, str, str, str)
        self.egoerazu.set_model(self.egoera)

        self.seinaleak = {"irtensim": self.irten,
                            "urratsez": self.urratsez,
                            "osoa": self.osoa,
                            "gelditu": self.amaitu,
                            "hurren": self.exekutatu,
                            "denborak": self.denborak,
                            "helbideak": self.helbideak,
                            "konpgorde": self.konpgorde,
                            "konpireki": self.konpireki,
                            "gorde": self.gorde,
                            "memazt": self.memazt,
                            "stat":self.stats}

        self.wZuhaitza.signal_autoconnect(self.seinaleak)
        if self.fitxategia:
            self.irakurri(self.fitxategia)
        self.irteera_berritu()


    #=========================================
    def irteera_berritu(self):
        self.output.set_text(self.irteera)

    def memoria_berritu(self):
        a = ""
        b = self.makina.dhasiera
        if self.makina.rodata>0:
            a+=".rodata\n"
            for i in range(b,b+self.makina.rodata):
                a+="@"+str(i)+"="+str(self.makina.aldagaiak[i-self.makina.dhasiera])+"\n"
        if self.makina.data>0:
            a+=".data\n"
            b+=self.makina.rodata
            for i in range(b,b+self.makina.data):
                a+="@"+str(i)+"="+str(self.makina.aldagaiak[i-self.makina.dhasiera])+"\n"
        if self.makina.bss>0:
            a+=".bss\n"
            b+=self.makina.data
            for i in range(b,b+self.makina.bss):
                a+="@"+str(i)+"="+str(self.makina.aldagaiak[i-self.makina.dhasiera])+"\n"
        if self.makina.text>0:
            a+="\n.text\n"
            b=self.makina.ahasiera
            for i in range(b,b+self.makina.text):
                a+="@"+str(i)+"="+str(hex(self.makina.aginduak[i-b]))[2:].zfill(4).upper()+"\n"

        self.memoria.set_text(a)

    def erregistroak_berritu(self):
        self.erregistro_lista.clear()
        for i in range(32):
            self.erregistro_lista.append(('r'+str(i).zfill(2)+':',str(self.makina.EM[i])))
        self.erregistro_lista.append(('---','-'*8))
        self.erregistro_lista.append(('IR:',self.makina.IR))
        self.erregistro_lista.append(('PC:',self.makina.PC))

    def zutabeak_gehitu(self, Zuhaitza, lista, aldagarria=True, ordenagarria=True):
        i=0
        for elementua in lista:
            self.zutabea_gehitu(Zuhaitza,elementua,i,aldagarria,ordenagarria)
            i+=1
    
    def zutabea_gehitu(self, Zuhaitza, izenburua, zenbakia, aldagarria=True, ordenagarria=True):
        zutabea = gtk.TreeViewColumn(izenburua, gtk.CellRendererText(), text=zenbakia)
        zutabea.set_resizable(aldagarria)
        if ordenagarria:
            zutabea.set_sort_column_id(zenbakia)
        Zuhaitza.append_column(zutabea)


    #=========================================


    def irakurri(self, fitxategia):
        self.irteera = ""
        self.egoera.clear()
        self.fitxategia = fitxategia
        self.makina.PC = self.makina.ahasiera
        self.btnhurrengoa.set_sensitive(True)
        self.btngelditu.set_sensitive(True)
        self.btngorde.set_sensitive(True)
        self.btnstat.set_sensitive(True)
        try:
            dock = open(self.fitxategia, 'r')
            mnumber = dock.read(5)
            if mnumber=='%PBIN':
                m = self.makina
                m.rodata,m.data,m.bss,m.text, m.aldagaiak, m.aginduak = tori.bin.read_plain_bin(dock)
                self.memoria_berritu()
            else:
                raise IOError
            dock.close()
        except IOError:
            tori.interface.informazioa(_("Adierazitako fitxategia ezin izan da irakurri."))
            raise Exception
        self.static_freq = [0 for i in range(len(self.makina.instruction_set))]
        for i in range(0,len(m.aginduak),2):
            self.static_freq[m.aginduak[i]/2**10]+=1
               

    def osokoa(self,katea):
        if katea[0]=='?':
            return random.randint(0,2**len(katea)-1)
        else:
            return int(katea,2)    

    def irakurri_bitarra(self, n):
        a = self.testua[:n]
        self.testua = self.testua[n:]
        return a

    def irakurri_katea(self):
        a=""
        i=0
        while self.testua[i:i+8] != '0'*8:
            a+=chr(int(self.testua[i:i+8],2))
            i+=8
        self.testua = self.testua[i+8:]
        return a


    #====Seinaleak==================
    def urratsez(self,w):
        if not self.fitxategia:
            fitxategia = tori.interface.hautatu_fitxategia("*.asm")
        fitxategia = self.fitxategia
        if fitxategia:
            self.irakurri(fitxategia)
            self.exekutatu()

    def exekutatu(self, w=None):
        ir1 = self.makina.aginduak[self.makina.PC-self.makina.ahasiera]
        ir2 = self.makina.aginduak[self.makina.PC-self.makina.ahasiera+1]
        self.makina.IR = (hex(ir1)[2:]+hex(ir2)[2:]).rstrip('L').zfill(8).upper()
        instruction = ir1/2**10
        ir1 = tori.binary.a_bitar_hutsa(ir1)
        ir2 = tori.binary.a_bitar_hutsa(ir2)
        self.makina.maiz_din[instruction]+=1
        self.makina.memoria_aztarna.append("A %d" % self.makina.PC)
        self.makina.memoria_aztarna.append("A %d" % (self.makina.PC+1))
        itzulitakoa=self.makina.instruction_set[instruction](ir1,ir2)
        self.egoera.append(itzulitakoa[0])
        if itzulitakoa[1]==-1:
            return self.amaitu("retm")
        elif itzulitakoa[1]!=None:
            self.irteera+=itzulitakoa[1]
            self.irteera_berritu()
        self.makina.PC+=2
        self.erregistroak_berritu()
        self.memoria_berritu()
        if self.makina.PC-self.makina.ahasiera >= self.makina.text:
            return self.amaitu()

    def osoa(self,w):
        if not self.fitxategia:
            fitxategia = tori.interface.hautatu_fitxategia("*.asm")
        else:
            fitxategia = self.fitxategia
        if fitxategia:
            self.irakurri(fitxategia)
            while self.makina.PC-self.makina.ahasiera <= self.makina.text \
                and not self.exekutatu():                
                while gtk.events_pending():
                    gtk.main_iteration()

    def amaitu(self,w=None):
        self.btnhurrengoa.set_sensitive(False)
        self.btngelditu.set_sensitive(False)
        if w==None:
            tori.interface.informazioa(_("Segmentation Fault: Baimenik gabeko memorian eragiketak."))
        elif w=="retm":
            tori.interface.informazioa(_("Simulazioa ZUZEN joan da."))
        return -1
        
    def denborak(self,w=None):
        a = tori.interface.formularioa(_("Latentzien definizioa(ns-tan)"),\
            ((_("Memoria irakurketa"),self.makina.denborak[0]),\
            (_("Memoria idazketa"),self.makina.denborak[1]),\
            (_("Deskodeketa"),self.makina.denborak[2]),\
            (_("Erregistro multzoko atzipenak"),self.makina.denborak[3]),\
            (_("Batuketa/kenketa"),self.makina.denborak[4]),\
            (_("Biderketa"),self.makina.denborak[5]),\
            (_("Zatiketa"),self.makina.denborak[6]),\
            (_("Eragiketa logikoa"),self.makina.denborak[7]),\
            (_("Desplazamendua"),self.makina.denborak[8]),\
            (_("Konparaketa"),self.makina.denborak[9]))\
            ,self.nagusia)
        if a and a!=self.makina.denborak:
            self.makina.denborak=a
    
    def helbideak(self,w=None):
        tori.interface.informazioa(_("Balioak aldatzen badituzu simulazioa geldiaraziko da"))
        a = tori.interface.formularioa(_("Hasiera helbideak"),((_("Datuen hasiera helbidea"),self.makina.dhasiera),\
            (_("Aginduen hasiera helbidea"),self.makina.ahasiera)),self.nagusia)
        if a and a!=(self.makina.dhasiera,self.makina.ahasiera):
            self.makina.dhasiera  = a[0]
            self.makina.ahasiera = a[1]
            self.amaitu(w)

    def konpgorde(self,w=None):
        path = tori.interface.hautatu_fitxategia('*.cfg',True)
        if path:
            f = open(path,'w')
            d = [self.makina.dhasiera,self.makina.ahasiera]
            d.extend(self.makina.denborak)
            for i in d:
                f.write(str(i)+'\n')
            f.close()

    def konpireki(self,w=None):
        path = tori.interface.hautatu_fitxategia('*.cfg',False)
        if path:
            f = open(path,'r')
            l = []
            for line in f:
                l.append(int(line))
            f.close()
            self.makina.dhasiera=l[0]
            self.makina.ahasiera=l[1]
            self.makina.denborak=tuple(l[2:])
    
    def gorde(self,w=None):
        print "TODO"#TODO

    #===============================

    def memazt(self,w):
        jat = w.get_name()
        if jat== "denxe":
            tit = _("Aginduen exekuzio denbora")+_("(Xehetua)")
            l = []
        else:
            tit = _("Memoria aztarna")
            l = self.makina.memoria_aztarna        
        tori.interface.lista(tit,l,self.nagusia)

    def stats(self,w):
        jat = w.get_name()
        if jat=="denlab":
            tit = _("Aginduen exekuzio denbora")+_("(Laburtua)")
            txt = "egiteke"
        elif jat=="maizlab":
            tit = _("Aginduen maiztasun estatikoa")+_("(Laburtua)")
            txt = "egiteke"
        elif jat=="maizxe":
            tit = _("Aginduen maiztasun estatikoa")+_("(Xehetua)")
            txt= self.maizxe()
        elif jat == "maizdixe":
            tit = _("Aginduen maiztasun dinamikoa")+_("(Xehetua)")
            txt = self.maizdinxe()
        elif jat == "maizdilab":
            tit = _("Aginduen maiztasun dinamikoa")+_("(Laburtua)")
            txt =  "egiteke"
        tori.interface.testua(tit,txt, self.nagusia)

    def maizdinxe(self):
        t="-------\t__#__\t__%__\n"       
        tot=n=0
        for i in self.makina.maiz_din: 
            tot+=i
        for i in [j[0] for j in tori.instructions.aginduak]:
            name  = i.upper().ljust(7)
            times = self.makina.maiz_din[n]
            perce = (float(times)/tot)*100
            t+="%s\t%s\t%02.2f\n"%(name, str(times).rjust(5), perce)
            n+=1 
        return t

    def maizxe(self):
        t="-------\t__#__\t__%__\n"
        for i in range(len(self.makina.instruction_names)):
            name = self.makina.instruction_names[i].ljust(7)
            times= self.static_freq[i]
            perce= float(times)/(len(self.makina.aginduak)/2)*100
            t+="%s\t%s\t%02.2f\n"%(name, str(times).rjust(5), perce)
        return t
    #===============================

    def hasi(self):
        gtk.main()
        
    def irten(self, w):
        self.nagusia.hide_all()
        gtk.main_quit()
        

itzultzeke = [
_("B"),
_("D"),
_("Ir"),
_("A"),
_("M"),
_("ld"),
_("Guztira"),
_("Exekuzio-denburak faseka"),
_("Bilaketa"),
_("Deskodeketa"),
_("Eragigaien irakurketa"),
_("EM"),
_("A(UAL)/Jauziak"),
_("Batuketa/Kenketa"),
_("Biderketa"),
_("Zatiketa"),
_("Logikoa"),
_("Desplazamendua"),
_("Jauziak (jmp/bxx)"),
_("Memoria"),
_("Irakurketa"),
_("Idazketa"),
_("Emaitzen idazketa"),
_("Bestelako atzipenak"),
_("IR (@,#,desp)"),
_("PCi(jmp,branch,call)"),
_("PC(call)"),
_("Aritmetiko/Logikoak"),
_("Mugimenduak"),
_("Memoria-atzipenak"),
_("Irakurketak"),
_("Absolutuak"),
_("Erlatiboak"),
_("Indexatuak"),
_("Idazketak"),
_("Jauziak"),
_("Baldintza gabekoak"),
_("Baldintzapekoak"),
_("Azpirrutinak"),
_("Deiak"),
_("Itzulerak"),
_("S/I"),
]    

